package com.global.emc.spring.method.support;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.global.emc.core.exception.impl.EMCException;
import com.global.emc.spring.method.support.chain.AfterCallMethodContent;
import com.global.emc.spring.method.support.chain.BeforeCallMethodContent;
import com.global.emc.spring.method.support.chain.CallMethodChain;

public class ChainInvocableHandlerMethodInterceptor extends BlankInvocableHandlerMethodInterceptor {
	
	private List<CallMethodChain> chains;

	public List<CallMethodChain> getChains() {
		return chains;
	}
	public void setChains(List<CallMethodChain> chains) {
		this.chains = chains;
	}

	@Override
	public Map<String,Object> before(
			Object obj,
			Method method,
			Object[] aobj,
			MethodParameter[] parameters,
			NativeWebRequest request,
			ModelAndViewContainer mavContainer,
			Object... providedArgs)throws EMCException {
		
		BeforeCallMethodContent beforeCallMethodContent = new BeforeCallMethodContent(obj, method, aobj, parameters,request,mavContainer, providedArgs);
		
		Map<String,Object> beforeCallMethodReturnValues = new HashMap<String,Object>();
		
		for(CallMethodChain chain : chains){
			Map<String,Object> beforeCallMethodReturnValue = chain.invoker(beforeCallMethodContent);
			if(null != beforeCallMethodReturnValue)
				beforeCallMethodReturnValues.putAll(beforeCallMethodReturnValue);
		}
		
		return beforeCallMethodReturnValues;
	}

	@Override
	public void after(
			Map<String,Object> beforeCallMethodReturnValues,
			Object returnValue,
			Object obj,
			Method method,
			Object[] aobj,
			MethodParameter[] parameters,
			NativeWebRequest request,
			ModelAndViewContainer mavContainer,
			Object... providedArgs) throws EMCException {
		
		AfterCallMethodContent afterCallMethodContent = new AfterCallMethodContent(beforeCallMethodReturnValues, returnValue, obj, method, aobj, parameters, request, mavContainer, providedArgs);
		
		for(CallMethodChain chain : chains){
			chain.invoker(afterCallMethodContent);
		}
		
	}


	
	
}
